/// -----------------------------------------------------------------------------------------------------------
/// Module      :  QueueStorageAdapterConnection.cs
/// Description :  Defines the connection to the target system.
/// -----------------------------------------------------------------------------------------------------------

#region Using Directives
using System;
using System.IO;
using System.Collections.Generic;
using System.Text;

using Microsoft.ServiceModel.Channels.Common;

using Microsoft.WindowsAzure;
using Microsoft.WindowsAzure.StorageClient;

#endregion

namespace BizTalkFactory.Adapters.AzureStorage
{
    internal class AzureStorageAdapterConnection : IConnection
    {
        #region Private Fields

        private AzureStorageAdapterConnectionFactory connectionFactory;
        private string connectionId;

        private CloudStorageAccount storageAccount = null;
        private CloudQueueClient queueStorage = null;
        private CloudBlobClient blobStorage = null;

        #endregion Private Fields

        /// <summary>
        /// Initializes a new instance of the QueueStorageAdapterConnection class with the QueueStorageAdapterConnectionFactory
        /// </summary>
        public AzureStorageAdapterConnection(AzureStorageAdapterConnectionFactory connectionFactory)
        {
            this.connectionFactory = connectionFactory;
            this.connectionId = Guid.NewGuid().ToString();
        }

        #region Public Properties

        /// <summary>
        /// Gets the ConnectionFactory
        /// </summary>
        public AzureStorageAdapterConnectionFactory ConnectionFactory
        {
            get { return this.connectionFactory; }
        }

        /// <summary>
        /// Gets the underlying Queue service client
        /// </summary>
        public CloudQueueClient QueueStorage
        {
            get
            {
                if (queueStorage == null)
                    queueStorage = storageAccount.CreateCloudQueueClient();

                return queueStorage;
            }
        }

        /// <summary>
        /// Gets the underlying Blob service client
        /// </summary>
        public CloudBlobClient BlobStorage
        {
            get
            {
                if (blobStorage == null)
                    blobStorage = storageAccount.CreateCloudBlobClient();

                return blobStorage;
            }
        }

        #endregion Public Properties

        #region IConnection Members

        /// <summary>
        /// Closes the connection to the target system
        /// </summary>
        public void Close(TimeSpan timeout)
        {
            if (blobStorage != null)
                blobStorage = null;

            if (queueStorage != null)
                queueStorage = null;

            if (storageAccount != null)
                storageAccount = null;
        }

        /// <summary>
        /// Returns a value indicating whether the connection is still valid
        /// </summary>
        public bool IsValid(TimeSpan timeout)
        {
            return (storageAccount != null);
        }

        /// <summary>
        /// Opens the connection to the target system.
        /// </summary>
        public void Open(TimeSpan timeout)
        {
            //System.Diagnostics.Debug.Assert(storageAccount == null);
            storageAccount = CloudStorageAccount.Parse(connectionFactory.ConnectionString);
        }

        /// <summary>
        /// Clears the context of the Connection. This method is called when the connection is set back to the connection pool
        /// </summary>
        public void ClearContext()
        {
            //
            //TODO: Implement clear context to set the connection back to the pool.
            //
        }

        /// <summary>
        /// Builds a new instance of the specified IConnectionHandler type
        /// </summary>
        public TConnectionHandler BuildHandler<TConnectionHandler>(MetadataLookup metadataLookup)
             where TConnectionHandler : class, IConnectionHandler
        {
            if (typeof(IInboundHandler).IsAssignableFrom(typeof(TConnectionHandler)))
                return new AzureStorageAdapterInboundHandler(this, metadataLookup) as TConnectionHandler;

            if (typeof(IMetadataBrowseHandler).IsAssignableFrom(typeof(TConnectionHandler)))
                return new AzureStorageAdapterMetadataBrowseHandler(this, metadataLookup) as TConnectionHandler;

            if (typeof(IMetadataResolverHandler).IsAssignableFrom(typeof(TConnectionHandler)))
                return new AzureStorageAdapterMetadataResolverHandler(this, metadataLookup) as TConnectionHandler;

            if (typeof(IOutboundHandler).IsAssignableFrom(typeof(TConnectionHandler)))
                return new AzureStorageAdapterOutboundHandler(this, metadataLookup) as TConnectionHandler;

            return default(TConnectionHandler);
        }

        /// <summary>
        /// Aborts the connection to the target system
        /// </summary>
        public void Abort()
        {
            //
            //TODO: Implement abort logic. DO NOT throw an exception from this method
            //
        }

        /// <summary>
        /// Gets the Id of the Connection
        /// </summary>
        public String ConnectionId
        {
            get { return connectionId; }
        }

        #endregion IConnection Members
    }
}
